﻿using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class LaserInputPointer : MonoBehaviour
{

	[DllImport ("YDLIDAR_DEMO")] extern static void StartRaidar ();
	[DllImport ("YDLIDAR_DEMO")] extern static void ScanOnce ();
	[DllImport ("YDLIDAR_DEMO")] extern unsafe static float * GetAxisX ();
	[DllImport ("YDLIDAR_DEMO")] extern unsafe static float * GetAxisY ();
	[DllImport ("YDLIDAR_DEMO")] extern static int GetBufferLength ();
	[DllImport ("YDLIDAR_DEMO")] extern static void Polar2Rect (float _a0, float _d0, float _a1, float _d1);

	GraphicRaycaster gr;
	EventSystem evt;

	bool isScanning = false;
	bool writingPoints = false;

	unsafe float * pX;
	unsafe float * pY;

	#region 极坐标→直角坐标
	//极坐标到直角坐标
	//a角是结果角度，d是*4的距离
	//d0 = d*4       !!!!!!!!!!!!!!!!!!!!!!!!!!!
	/*


		···························   (a0, d0)
		|						  |
		|						  |
		|						  |
		|						  |
		···························   (a1, d1)
					·→  (0, ∞)
	*/

	float a0;
	float d0;

	float a1;
	float d1;

	#endregion

	#region 直角坐标→屏幕坐标

	//屏幕尺寸
	[SerializeField] static readonly int width = 1920;
	[SerializeField] static readonly int height = 1080;

	#endregion

	ConcurrentQueue<Vector2> q = new ConcurrentQueue<Vector2> ();
	RectTransform canvas;

	bool keepScan = true;

	void Start ()
	{
		canvas = GetComponent<RectTransform> ();
		
		//初始化
		evt = GetComponent<EventSystem> ();
		gr = GetComponent<GraphicRaycaster> ();

		//传入转换参数
		Polar2Rect (41.6f, 1204, 90, 800);

		//启动雷达
		StartRaidar ();

		unsafe
		{
			pX = GetAxisX ();
			pY = GetAxisY ();
		}
	}

	private void Update ()
	{
		if (keepScan)
			Scan ();

		if (q.Count > 0)
		{
			for (int i = 0; i < q.Count; i++)
			{
				Vector2 vec2;
				q.TryDequeue (out vec2);
				SimTouch (ScreenCoorClickPos (vec2));
			}
		}

		if (Input.GetKeyDown (KeyCode.P))
			keepScan = false;
	}

	//
	public void SimTouch (PointerEventData ped)
	{
		var rs = new List<RaycastResult> ();
		gr.Raycast (ped, rs);

		try
		{
			//GameObject obj = Instantiate (Resources.Load ("Point"), canvas) as GameObject;
			//obj.GetComponent<RectTransform> ().position = ped.position;
			rs[0].gameObject.GetComponent<NvshuWord> ().Use ();
		}
		catch (System.Exception) { }
	}

	//现在已经把极坐标到屏幕坐标的转换放在C++代码里了
	public PointerEventData ScreenCoorClickPos (Vector2 v)
	{
		EventSystem evt = EventSystem.current;
		var ped = new PointerEventData (evt)
		{
			position = v
		};

		return ped;
	}

	//有个旗子来判断
	async void Scan ()
	{

		//如果已经在扫描过程中了
		if (isScanning)
			return;

		isScanning = true;
		await Task.Run (() =>
		{
			writingPoints = true;
			ScanOnce ();

			int len = GetBufferLength ();

			for (int i = 0; i < len; i++)
			{
				unsafe
				{
					q.Enqueue (new Vector2 (pX[i] * 1920, pY[i] * 1080));
				}
			}
			writingPoints = false;

		});

		//重置旗子
		isScanning = false;

	}

}